# -*- coding: utf-8 -*-
# created on 2016/12/22
from sympy import sympify, solve, S, solveset
from mathsolver.functions.base import BaseFunction, BaseFuncEq, BaseFunc, BaseNumber, new_latex, BasePieceFunc
from mathsolver.functions.hanshu.helper import check_inter, yizhizhiyu_qiufanwei
from mathsolver.functions.hanshu.zhouqi import HanShuZhouQi, has_f, zhouqi_dingyishi
from mathsolver.functions.sympy_utils import get_all_child, default_symbol


class ZhouQiQiuZhi(BaseFunction):
    """函数周期性求函数的值"""

    def solver(self, *args):
        # 处理输入
        func, funceq_or_t, funcname = args

        # 已知 f(a) = b, 求 f(c)
        a, b = sympify(func.value['var']), sympify(func.value['expression'])
        c = funcname.var

        if isinstance(funceq_or_t, BaseFuncEq):
            # 如果题目给定 关系式，例如：f(x+3) = 1/(-f(x))
            zhouqi_step = HanShuZhouQi().solver(funceq_or_t)
            self.steps.extend(zhouqi_step.steps)
            zt = zhouqi_step.output[0].value

            # 求出 f(a + T/2) 和 f(a - T/2) 的值
            left, right = sympify(funceq_or_t.value)
            expr = left - right
            symbol = default_symbol(expr)
            fxs = set(get_all_child(expr, has_f))

            var_vals = {a: b}
            for fx in fxs:
                inner_fx = fx.args[0]
                x = solve(inner_fx - a, symbol, domain=S.Reals)[0]
                new_expr = expr.subs(symbol, x).subs(sympify('%s(%s)' % (funcname.name, a)), b)
                f_new = get_all_child(new_expr, has_f)[0]
                f_new_var = f_new.args[0]
                f_new_val = solve(new_expr, f_new)[0]
                var_vals[f_new_var] = f_new_val

            # 推导 f(c) 的值
            for var in var_vals.keys():
                if (c - var) % zt == 0:
                    res = var_vals[var]
                    self.steps.append(["", "根据给定条件可以得 f({var}) = {res}".format(var=var, res=res)])
                    self.steps.append(["", "{eq} = f({m}*{T} + {var}) = f({var}) = {res}"
                                      .format(eq=funcname.printing(), T=zt, var=var, m=(c - var) / zt, res=res)])
                    break
        else:
            zt = funceq_or_t.sympify()
            if (c - a) % zt == 0:
                res = b
                self.steps.append(["", "{eq} = f({m}*{T} + {a}) = f({a}) = {res}".
                                  format(eq=funcname.printing(), m=(c - a) / zt, T=zt, a=a, res=res)])

        self.label.add("函数周期性求函数的值")
        self.output.append(BaseNumber(res))
        return self


class ZhouQiQiuZhiJieXiShi(BaseFunction):
    """函数周期性求函数的值——函数解析式"""

    def solver(self, *args):
        # 处理输入
        func, interval, zt, funcname = args
        expr, var = sympify(func.value['expression']), sympify(func.value['var'])
        dd = check_inter(interval)
        zt = sympify(zt.value)
        q_var = funcname.var

        # 周期定义
        relation, step = zhouqi_dingyishi(zt)
        self.steps.append(['', step])
        self.steps.append(["", "把 x = %s 代入，得 %s" % (q_var, new_latex(relation.subs(var, q_var)))])

        biaodashi = relation.rhs.subs(var, q_var).args[0]
        fanwei = yizhizhiyu_qiufanwei(biaodashi, dd)
        self.steps.append(["", "解 %s ∈ %s 得出 n ∈ %s" % (biaodashi, dd, fanwei)])
        low = fanwei._inf
        n = int(low) if int(low) in fanwei else int(low + 1)
        self.steps.append(["", "得到 n = %s" % n])
        var_final = biaodashi.subs(sympify('n'), n)

        # 分段函数
        if isinstance(func, BasePieceFunc):
            res = func.run(var_final)
        else:
            res = expr.subs(var, var_final)

        self.steps.append(["", "所以 %s = f(%s) = %s" % (funcname.printing(), var_final, res)])

        self.output.append(BaseNumber(res))
        self.label.add("函数周期性求函数的值——函数解析式")
        return self


class ZhouQiJieXiShi(BaseFunction):
    """函数周期性求函数的解析式"""

    def solver(self, *args):
        zt, inter, func, q_inter = args
        zt = sympify(zt.value)
        expr, var = func.expression, func.var

        # step1: 函数周期定义式
        relation, step = zhouqi_dingyishi(zt)
        fxplusnt = relation.rhs
        xplusnt = fxplusnt.args[0]
        self.steps.append(["", step])

        # step2: x ∈ q_inter, 求 n 使得 x+2*n ∈ inter
        low, low2 = inter._inf, q_inter._inf
        n = solveset(xplusnt.subs(var, low2) - low).args[0]
        self.steps.append(["", "当 x ∈ %s 时，令 n = %s， 则 %s ∈ %s " % (q_inter, n, var + zt * n, inter)])

        # step3: 代入求值
        new_var = fxplusnt.args[0].subs(sympify('n'), n)
        new_expr = expr.subs(var, new_var)
        self.steps.append(["", "将 %s 代入 %s 得 f(x) = %s" % (new_var, expr, new_expr)])

        self.output.append(BaseFunc({"var": var, "name": func.name, "type": "", "expression": new_expr}))
        self.label.add("函数周期性求函数的解析式")
        return self


if __name__ == '__main__':
    pass
